<template>
    <div class="vir-editor">
        <slot name="toolbar"></slot>
        <div ref="editor" class="vir-editor-body"></div>
    </div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import Quill from 'quill';

import 'quill/dist/quill.snow.css';

export const DefaultModules = {
    toolbar: [
        ['bold', 'italic', 'underline', 'strike'],
        [{ header: [1, 2, 3, 4, 5, 6, false] }],
        [{ size: ['small', false, 'large', 'huge'] }],
        ['align', 'color', 'background'],
        ['blockquote', 'code-block', 'link', 'image']
    ]
};

@Component
export default class VirEditor extends Vue {
    private componentEditor?: Quill;
    private content?: string;

    @Prop({ default: () => '' })
    private value?: string;

    @Prop({ default: () => false })
    private disabled?: boolean;

    @Prop({ default: () => DefaultModules })
    private modules?: any;

    @Prop({ default: () => 'Compose an epic...' })
    private placeholder?: string;

    @Prop({ default: () => undefined })
    private readOnly?: boolean;

    set editor(val: Quill) {
        this.componentEditor = val;
    }

    get editor(): Quill {
        return this.componentEditor as Quill;
    }

    private mounted() {
        this.editor = new Quill(this.$refs.editor as Element, {
            placeholder: this.placeholder,
            readOnly: this.readOnly,
            modules: this.modules,
            theme: 'snow'
        });

        this.editor.enable(!this.disabled);
        this.editor.pasteHTML(this.value as string);

        // 绑定文本编辑事件
        this.editor.on('text-change', (delta, oldDelta, source) => {
            if (source === 'api') return;

            const editor = this.editor;
            const text = editor.getText();
            const html = editor.root.innerHTML;

            if (html !== '<p><br></p>') {
                this.content = html;
                this.$emit('input', html);
                this.$emit('change', { html, text, editor });
            } else {
                this.content = '';
                this.$emit('input', '');
                this.$emit('change', { text, editor });
            }
        });

        // 完成初始化
        this.$emit('ready', this.editor);
    }

    private destroyed() {
        this.componentEditor = undefined;
    }

    @Watch('value')
    private watchValue(newVal: string, oldVal: string) {
        if (!this.componentEditor) return;

        if (newVal && newVal !== this.content) {
            this.content = newVal;
            this.editor.pasteHTML(newVal, 'api');
        } else if (!newVal) {
            this.content = '';
            this.editor.setText('', 'api');
        }
    }

    @Watch('disabled')
    private watchDisabled(newVal: boolean, oldVal: boolean) {
        if (!this.componentEditor) return;

        this.editor.enable(!newVal);
    }
}
</script>
<style lang="scss" scoped>
.vir-editor {
  line-height: initial;

  .vir-editor-body {
    height: 350px;
  }
}
</style>
